package com.sky.loveshop.service.impl;

import cn.hutool.core.date.DateUtil;
import com.sky.loveshop.entity.OpenDoorHistory;
import com.sky.loveshop.entity.Shop;
import com.sky.loveshop.entity.common.SysConstants;
import com.sky.loveshop.entity.exception.BizException;
import com.sky.loveshop.entity.exception.BizExceptionEnum;
import com.sky.loveshop.manager.MqttClientManager;
import com.sky.loveshop.service.*;
import com.sky.loveshop.utils.QiYeWeChatSendMsgUtil;
import com.sky.loveshop.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

import static com.sky.loveshop.entity.common.SysConstants.OPEN_DOOR_QI_YE_WECHAT_GROUP_01_KEY;

/**
 * @author xcy
 * @version V1.0
 * @description
 * @date 2024/10/31 23:48
 */
@Slf4j
@Service
public class IotServiceImpl implements IotService {

    @Resource
    private MqttClientManager mqttClientManager;
    @Autowired
    private MqttClientService mqttClientService;
    @Autowired
    private MqttTopicService mqttTopicService;
    @Autowired
    private MqttCommandService mqttCommandService;
    @Autowired
    private ShopService shopService;
    @Autowired
    private OpenDoorHistoryService openDoorHistoryService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private QiYeWeChatSendMsgUtil qiYeWeChatSendMsgUtil;


    @Override
    public String openDoorAfterCheck(Integer shopId) throws BizException {

        checkOpenFlag(shopId);

        // 发布客户端
        String publisher = mqttClientService.getPublisher(shopId);
        // 主题
        String topicPath = mqttTopicService.getTopicPathByShopIdAndType(shopId, SysConstants.COMMAND_TYPE_OPEN_DOOR);
        // 指令
        String commandContent = mqttCommandService.getCommandByType(SysConstants.COMMAND_TYPE_OPEN_DOOR);

        Shop shop = shopService.getShopById(shopId);
        OpenDoorHistory history = new OpenDoorHistory();
        history.setWxMiniUserId(9999);
        history.setPhone("13000000000");
        history.setShopId(shopId);
        history.setShopName(shop.getName());
        history.setOpenTime(new Date());
        history.setLocation(shop.getLnt() + "," + shop.getLat());
        history.setSendResult(1);
        history.setOpenType(2);
        openDoorHistoryService.addOpenDoorHistory(history);

        String msg = assembleOpenDoorMsg(shop.getName(), shop.getAddress(), "骑手核销完成后开门", DateUtil.formatDateTime(new Date()));
        qiYeWeChatSendMsgUtil.sendMarkdownMsg(OPEN_DOOR_QI_YE_WECHAT_GROUP_01_KEY, msg);

        try {
            MqttMessage mqttMessage = new MqttMessage(commandContent.getBytes());
            mqttClientManager.getMqttClientById(publisher).publish(topicPath, mqttMessage);
            log.info("openDoorAfterCheck pubPub 骑手核销完成后开门成功 shopId={} publisher={} topicPath={} commandContent={}", shopId, publisher, topicPath, commandContent);
            return "发送成功";
        } catch (Exception e) {
            log.error("openDoorAfterCheck pubPub 骑手核销完成后开门失败 shopId={} publisher={} topicPath={} commandContent={}", shopId, publisher, topicPath, commandContent, e);
            e.printStackTrace();

            // 更新状态为下发失败
            history.setSendResult(0);
            history.setUpdateTime(new Date());
            openDoorHistoryService.updateOpenDoorHistoryById(history);

            return "发送失败";
        }
    }

    /**
     * 组装开门通知消息
     *
     * @param shopName 商店名称
     * @param address  商店地址
     * @param openType 开门类型 用户扫码开门|骑手扫码开门|后台管理开门|用户线下购买支付成功后开门|骑手核销完成后开门
     * @param openTime 开门时间
     */
    private String assembleOpenDoorMsg(String shopName, String address, String openType, String openTime) {
        StringBuilder msg = new StringBuilder();
        msg.append("#### 门店开门通知\n");
        msg.append(">商店名称：").append(shopName).append("\n");
        msg.append(">商店地址：").append(address).append("\n");
        msg.append(">开门类型：").append(openType).append("\n");
        msg.append(">开门时间：").append(openTime).append("\n");
        return msg.toString();
    }

    @Override
    public String openDoorAfterPay(Integer shopId) throws BizException {

        checkOpenFlag(shopId);

        // 发布客户端
        String publisher = mqttClientService.getPublisher(shopId);
        // 主题
        String topicPath = mqttTopicService.getTopicPathByShopIdAndType(shopId, SysConstants.COMMAND_TYPE_OPEN_DOOR);
        // 指令
        String commandContent = mqttCommandService.getCommandByType(SysConstants.COMMAND_TYPE_OPEN_DOOR);

        Shop shop = shopService.getShopById(shopId);
        OpenDoorHistory history = new OpenDoorHistory();
        history.setWxMiniUserId(9999);
        history.setPhone("13000000000");
        history.setShopId(shopId);
        history.setShopName(shop.getName());
        history.setOpenTime(new Date());
        history.setLocation(shop.getLnt() + "," + shop.getLat());
        history.setSendResult(1);
        history.setOpenType(1);
        openDoorHistoryService.addOpenDoorHistory(history);

        String msg = assembleOpenDoorMsg(shop.getName(), shop.getAddress(), "用户线下购买支付后开门", DateUtil.formatDateTime(new Date()));
        qiYeWeChatSendMsgUtil.sendMarkdownMsg(OPEN_DOOR_QI_YE_WECHAT_GROUP_01_KEY, msg);

        try {
            MqttMessage mqttMessage = new MqttMessage(commandContent.getBytes());
            mqttClientManager.getMqttClientById(publisher).publish(topicPath, mqttMessage);
            log.info("openDoorAfterCheck pubPub 用户线下购买支付后开门成功 shopId={} publisher={} topicPath={} commandContent={}", shopId, publisher, topicPath, commandContent);
            return "发送成功";
        } catch (Exception e) {
            log.error("openDoorAfterCheck pubPub 用户线下购买支付后开门失败 shopId={} publisher={} topicPath={} commandContent={}", shopId, publisher, topicPath, commandContent, e);
            e.printStackTrace();

            // 更新状态为下发失败
            history.setSendResult(0);
            history.setUpdateTime(new Date());
            openDoorHistoryService.updateOpenDoorHistoryById(history);

            return "发送失败";
        }
    }

    @Override
    public String openDoorByAdmin(Integer shopId) throws BizException {

        checkOpenFlag(shopId);

        // 发布客户端
        String publisher = mqttClientService.getPublisher(shopId);
        // 主题
        String topicPath = mqttTopicService.getTopicPathByShopIdAndType(shopId, SysConstants.COMMAND_TYPE_OPEN_DOOR);
        // 指令
        String commandContent = mqttCommandService.getCommandByType(SysConstants.COMMAND_TYPE_OPEN_DOOR);

        Shop shop = shopService.getShopById(shopId);
        OpenDoorHistory history = new OpenDoorHistory();
        history.setWxMiniUserId(9998);
        history.setPhone("13000000001");
        history.setShopId(shopId);
        history.setShopName(shop.getName());
        history.setOpenTime(new Date());
        history.setLocation(shop.getLnt() + "," + shop.getLat());
        history.setSendResult(1);
        history.setOpenType(3);
        openDoorHistoryService.addOpenDoorHistory(history);

        String msg = assembleOpenDoorMsg(shop.getName(), shop.getAddress(), "后台管理远程开门", DateUtil.formatDateTime(new Date()));
        qiYeWeChatSendMsgUtil.sendMarkdownMsg(OPEN_DOOR_QI_YE_WECHAT_GROUP_01_KEY, msg);

        try {
            MqttMessage mqttMessage = new MqttMessage(commandContent.getBytes());
            mqttClientManager.getMqttClientById(publisher).publish(topicPath, mqttMessage);
            log.info("openDoorByAdmin pubPub 后台管理远程开门成功 shopId={} publisher={} topicPath={} commandContent={}", shopId, publisher, topicPath, commandContent);
            return "发送成功";
        } catch (Exception e) {
            log.error("openDoorByAdmin pubPub 后台管理远程开门失败 shopId={} publisher={} topicPath={} commandContent={}", shopId, publisher, topicPath, commandContent, e);
            e.printStackTrace();

            // 更新状态为下发失败
            history.setSendResult(0);
            history.setUpdateTime(new Date());
            openDoorHistoryService.updateOpenDoorHistoryById(history);

            return "发送失败";
        }
    }

    @Override
    public String openAlarm(Integer shopId) {
        // 发布客户端
        String publisher = mqttClientService.getPublisher(shopId);
        // 主题
        String topicPath = mqttTopicService.getTopicPathByShopIdAndType(shopId, SysConstants.COMMAND_TYPE_ALARM);
        // 指令
        String commandContent = mqttCommandService.getCommandByType(SysConstants.COMMAND_TYPE_ALARM);
        try {
            MqttMessage mqttMessage = new MqttMessage(commandContent.getBytes());
            mqttClientManager.getMqttClientById(publisher).publish(topicPath, mqttMessage);
            log.info("openAlarm pubPub 远程开启告警成功 shopId={} publisher={} topicPath={} commandContent={}", shopId, publisher, topicPath, commandContent);
            return "发送成功";
        } catch (Exception e) {
            log.error("openAlarm pubPub 远程开启告警失败 shopId={} publisher={} topicPath={} commandContent={}", shopId, publisher, topicPath, commandContent, e);
            e.printStackTrace();
            return "发送失败";
        }
    }

    @Override
    public String switchSensor(Integer shopId) {
        // 发布客户端
        String publisher = mqttClientService.getPublisher(shopId);
        // 主题
        String topicPath = mqttTopicService.getTopicPathByShopIdAndType(shopId, SysConstants.COMMAND_TYPE_SENSOR_MODE);
        // 指令
        String commandContent = mqttCommandService.getCommandByType(SysConstants.COMMAND_TYPE_SENSOR_MODE);
        try {
            MqttMessage mqttMessage = new MqttMessage(commandContent.getBytes());
            mqttClientManager.getMqttClientById(publisher).publish(topicPath, mqttMessage);
            log.info("switchSensor pubPub 切换感应模式成功 shopId={} publisher={} topicPath={} commandContent={}", shopId, publisher, topicPath, commandContent);
            return "发送成功";
        } catch (Exception e) {
            log.error("switchSensor pubPub 切换感应模式失败 shopId={} publisher={} topicPath={} commandContent={}", shopId, publisher, topicPath, commandContent, e);
            e.printStackTrace();
            return "发送失败";
        }
    }

    @Override
    public String switchScan(Integer shopId) {
        // 发布客户端
        String publisher = mqttClientService.getPublisher(shopId);
        // 主题
        String topicPath = mqttTopicService.getTopicPathByShopIdAndType(shopId, SysConstants.COMMAND_TYPE_SCAN_MODE);
        // 指令
        String commandContent = mqttCommandService.getCommandByType(SysConstants.COMMAND_TYPE_SCAN_MODE);
        try {
            MqttMessage mqttMessage = new MqttMessage(commandContent.getBytes());
            mqttClientManager.getMqttClientById(publisher).publish(topicPath, mqttMessage);
            log.info("switchScan pubPub 切换扫码模式成功 shopId={} publisher={} topicPath={} commandContent={}", shopId, publisher, topicPath, commandContent);
            return "发送成功";
        } catch (Exception e) {
            log.error("switchScan pubPub 切换扫码模式失败 shopId={} publisher={} topicPath={} commandContent={}", shopId, publisher, topicPath, commandContent, e);
            e.printStackTrace();
            return "发送失败";
        }
    }

    @Override
    public String userOpenDoorByMini(Integer shopId, String phone) throws BizException {

        checkOpenFlag(shopId);

        // 发布客户端
        String publisher = mqttClientService.getPublisher(shopId);
        // 主题
        String topicPath = mqttTopicService.getTopicPathByShopIdAndType(shopId, SysConstants.COMMAND_TYPE_OPEN_DOOR);
        // 指令
        String commandContent = mqttCommandService.getCommandByType(SysConstants.COMMAND_TYPE_OPEN_DOOR);
        try {
            MqttMessage mqttMessage = new MqttMessage(commandContent.getBytes());
            mqttClientManager.getMqttClientById(publisher).publish(topicPath, mqttMessage);
            log.info("userOpenDoorByMini pubPub 骑手/用户线下通过微信门禁小程序开门 shopId={}, phone={} publisher={} topicPath={} commandContent={}", shopId, phone, publisher, topicPath, commandContent);
            return "发送成功";
        } catch (Exception e) {
            log.error("userOpenDoorByMini pubPub 骑手/用户线下通过微信门禁小程序开门 shopId={}, phone={} publisher={} topicPath={} commandContent={}", shopId, phone, publisher, topicPath, commandContent, e);
            e.printStackTrace();
            return "发送失败";
        }
    }

    @Override
    public Integer forceDisableDoor(Integer shopId) {
        String key = String.format(SysConstants.SHOP_CAN_OPEN_DOOR_FLAG_KEY, shopId);
        redisTemplate.opsForValue().set(key, "yes");
        return 1;
    }

    @Override
    public Integer removeForceDisableDoor(Integer shopId) {
        String key = String.format(SysConstants.SHOP_CAN_OPEN_DOOR_FLAG_KEY, shopId);
        redisTemplate.opsForValue().set(key, "no");
        return 1;
    }

    /**
     * 校验门禁是否处于强制锁定无法开门状态
     */
    private void checkOpenFlag(Integer shopId) throws BizException {
        String key = String.format(SysConstants.SHOP_CAN_OPEN_DOOR_FLAG_KEY, shopId);
        String value = redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotEmpty(value) && "yes".equals(value)) {
            throw new BizException(BizExceptionEnum.CAN_NOT_OPEN_SHOP_NOW);
        }
    }

}
